class SpaceShipController {
    void up(int velocity) {
    }

    void down(int velocity) {
    }

    void left(int velocity) {
    }

    void right(int velocity) {
    }

    void forward(int velocity) {
    }

    void back(int velocity) {
    }

    void turboBoost() {
    }
}

class DerivedSpaceShip extends SpaceShipController {
    private String name;

    public DerivedSpaceShip(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name + ": {" + super.toString() + "}";
    }
}

class SpaceShipDelegation {
    private String name;
    private SpaceShipController controller = new SpaceShipController();

    public SpaceShipDelegation(String name) {
        this.name = name;
    }

    // 委托方法
    public void up(int velocity) {
        controller.up(velocity);
    }

    public void down(int velocity) {
        controller.down(velocity);
    }

    public void left(int velocity) {
        controller.left(velocity);
    }

    public void right(int velocity) {
        controller.right(velocity);
    }

    public void forward(int velocity) {
        controller.forward(velocity);
    }

    public void back(int velocity) {
        controller.back(velocity);
    }

    public void turboBoost() {
        controller.turboBoost();
    }
}

public class DelegationDemo {
    public static void main(String[] args) {
        // DerivedSpaceShip并非真正的SpaceShipControls类型，即使DerivedSpaceShip调用forward()方法。
        DerivedSpaceShip f = new DerivedSpaceShip("X-Wing");
        f.forward(100);

        // 方法调用被转发到了内部的controls对象，因此这里得到的接口与使用继承得到的是相同的。
        // 但是，这里可以更好地控制委托，因为可以选择仅提供成员对象中的部分方法。
        SpaceShipDelegation spaceShipDelegation = new SpaceShipDelegation("X-Wing");
        spaceShipDelegation.forward(100);
    }
}

/*
 Java 语言本身没有内置的 委托（delegation） 关键字或语法结构，
 但现代 IDE（如 JetBrains IDEA）可以通过辅助生成代码的方式实现类似“委托”的行为。

Java 不直接支持委托机制
在 Java 中，并不像某些语言（如 C#）那样有 delegate 关键字来声明一个委托类型。
所以 Java 要实现委托逻辑，需要手动编写代码，比如在类中包含另一个对象，并将方法调用转发给该对象。

IDE 支持自动创建委托方法
上下文中的 SpaceShipDelegation 类就是通过手动方式实现委托的例子：它内部持有一个 SpaceShipController 对象，并为每个方法都编写了一个转发方法。
虽然这些方法是手动编写的，但在实际开发中，像 IntelliJ IDEA 这样的工具可以自动生成这些“转发”方法：
比如使用 Code > Generate > Delegate Methods 功能，选择某个成员变量后，IDEA 可以自动为该对象的所有方法生成包装方法。

继承 vs 委托（示例中的对比）
DerivedSpaceShip 是通过 继承（extends） 的方式获得 SpaceShipController 的功能；
SpaceShipDelegation 是通过 组合 + 方法转发（委托） 的方式实现相同的功能。
使用委托的一个优势是可以更灵活地控制暴露哪些方法，而不是继承整个接口。
 */